home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
cpicker
/
Cpick.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-22
|
47KB
|
1,513 lines
/*****************************************************************
Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Digital or MIT not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
******************************************************************/
/*
* Cpick.c - Color picker widget for Motif Toolkit
*
* Author: Mike Yang (mikey@sgi.com)
* Silicon Graphics, Inc.
* Date: Mon Jul 29 1991
* Copyright (c) 1988, 1991 Mike Yang
*
*/
#include <stdio.h>
#include <math.h>
#include <X11/Xos.h>
#include <Xm/ManagerP.h>
#include "CpickP.h"
#include <Xm/Form.h>
#include <Xm/RowColumn.h>
#include <Xm/Label.h>
#include <Xm/LabelG.h>
#include <Xm/Scale.h>
#include <Xm/Frame.h>
#include <Xm/DrawingA.h>
#include <Xm/PushB.h>
#include <Xm/Text.h>
#include <Xm/TextF.h>
#include <Xm/SelectioB.h>
#include "color.h"
#include <X11/Shell.h>
/* #define BUBBLE_MATCH /* Uses a visible bubble sort when matching colors */
#define INCREMENT 10
#define WIDENEAR 8192
#define NARROWNEAR 768
#define MAXIMUM 65536
#define MINIMUM 0
#define MBASE 256
#define RATIO (MAXIMUM/MBASE)
#define FBASE 1000
#define NULLSTR " "
#define RGBFILE "/usr/lib/X11/rgb.txt"
/* These should be resources */
#define BORDER_MARGIN 20
#define INTRA_SCALE_SPACING 5
#define SCALE_SPACING 5
#define SCALE_SET_SPACING 20
#define INTER_SPACING 10
#define SCALE_WIDTH 100
#define BOX_MARGIN 10
#define BOX_SHADOW_THICKNESS 4
#define BUTTON_SPACING 4
#define WIDE_STRING "Wide"
#define RANGE_STRING "Range"
#define NARROW_STRING "Narrow"
#define MATCH_STRING "Match"
#define Offset(field) XtOffset(CpickWidget, field)
static XtResource resources[] = {
{XmNhelpProc, XmCCallback, XmRCallback, sizeof(XtPointer),
Offset(cpick.helpProc), XmRCallback, NULL},
{XmNokProc, XmCCallback, XmRCallback, sizeof(XtPointer),
Offset(cpick.okProc), XmRCallback, NULL},
{XmNselectProc, XmCCallback, XmRCallback, sizeof(XtPointer),
Offset(cpick.selectProc), XmRCallback, NULL},
{XmNchangeProc, XmCCallback, XmRCallback, sizeof(XtPointer),
Offset(cpick.changeProc), XmRCallback, NULL},
{XmNrestoreProc, XmCCallback, XmRCallback, sizeof(XtPointer),
Offset(cpick.restoreProc), XmRCallback, NULL},
{XmNallocated, XmCAllocated, XmRXColor, sizeof(XtPointer),
Offset(cpick.allocated), XmRXColor, NULL},
{XmNcmap, XmCCmap, XmRColormap, sizeof(Colormap),
Offset(cpick.cmap), XmRColormap, NULL},
{XmNselectLabel, XmCLabel, XmRString, sizeof(String),
Offset(cpick.selectlabel), XmRString, "Select"},
{XmNcancelLabel, XmCLabel, XmRString, sizeof(String),
Offset(cpick.cancellabel), XmRString, "Cancel"},
{XmNrestoreLabel, XmCLabel, XmRString, sizeof(String),
Offset(cpick.restorelabel), XmRString, "Restore"},
{XmNhelpLabel, XmCLabel, XmRString, sizeof(String),
Offset(cpick.helplabel), XmRString, "Help"},
{XmNokLabel, XmCLabel, XmRString, sizeof(String),
Offset(cpick.oklabel), XmRString, "OK"},
{XmNnearPixels, XmCDimension, XmRDimension, sizeof(Dimension),
Offset(cpick.nearpixels), XmRString, "64"},
{XmNuseColors, XmCUsecolors, XmRBoolean, sizeof(Boolean),
Offset(cpick.usecolors), XmRString, "False"},
};
static void ClassInitialize();
static void Initialize();
static void Realize();
static void Resize();
static void Redisplay();
static Boolean SetValues();
static XtGeometryResult GeometryManager();
static void ChangeManaged();
static int changeLabel();
static int doNew();
static int doExpose();
static int changePalette();
static int undomatch();
static int matchPalette();
static void setMlabelStr();
static void Notify();
CpickClassRec cpickClassRec = {
{
(WidgetClass) &xmManagerClassRec, /* superclass */
"Cpick", /* class_name */
sizeof(CpickRec), /* size */
NULL, /* class_initialize */
NULL, /* class_part_initialize */
FALSE, /* class_inited */
Initialize, /* initialize */
NULL, /* initialize_hook */
Realize, /* realize */
NULL, /* actions */
0, /* num_actions */
resources, /* resources */
XtNumber(resources), /* resource_count */
NULLQUARK, /* xrm_class */
TRUE, /* compress_motion */
TRUE, /* compress_exposure */
TRUE, /* compress_enterleave */
FALSE, /* visible_interest */
NULL, /* destroy */
Resize, /* resize */
XtInheritExpose, /* expose */
SetValues, /* set_values */
NULL, /* set_values_hook */
XtInheritSetValuesAlmost, /* set_values_almost */
NULL, /* get_values_hook */
NULL, /* accept_focus */
XtVersion, /* version */
NULL, /* callback_private */
NULL, /* tm_table */
NULL, /* query_geometry */
XtInheritDisplayAccelerator, /* display_accelerator */
NULL /* extension */
},{
/* composite_class fields */
/* geometry_handler */ GeometryManager,
/* change_managed */ ChangeManaged,
/* insert_child */ XtInheritInsertChild,
/* delete_child */ XtInheritDeleteChild,
/* extension */ NULL
},{
/* constraint class record */
/* no additional resources */ NULL,
/* num additional resources */ 0,
/* size of constraint rec */ 0,
/* constraint_initialize */ NULL,
/* constraint_destroy */ NULL,
/* constraint_setvalue */ NULL,
/* extension */ NULL,
},{
/* manager class record */
XtInheritTranslations, /* default translations */
NULL, /* syn_resources */
0, /* num_syn_resources */
NULL, /* syn_cont_resources */
0, /* num_syn_cont_resources */
XmInheritParentProcess, /* parent_process */
NULL, /* extension */
},{
/* Cpick class fields */
/* empty */ 0,
}
};
WidgetClass cpickWidgetClass = (WidgetClass)&cpickClassRec;
typedef unsigned long (*PixProc)();
struct vals {
int ih, iw, x0, y0, rownum;
PixProc pix;
CpickWidget cw;
} nval;
String colors[] = {"red", "green", "blue",
"gold", "khaki", "wheat",
"cyan", "magenta", "yellow"};
static char STRING[] = "rgbhsvcmy";
static Arg args[20];
static int count;
static Position getP(w, s)
Widget w;
String s;
{
Position result;
int v;
count = 0;
XtSetArg(args[count], s, (XtArgVal) &result); count++;
XtGetValues(w, args, count);
v = result;
return(v);
}
static Dimension getD(w, s)
Widget w;
String s;
{
Dimension result;
int v;
count = 0;
XtSetArg(args[count], s, (XtArgVal) &result); count++;
XtGetValues(w, args, count);
v = result;
return(v);
}
static SetScaleValue(CpickWidget cw, int which, int value)
{
XmScaleSetValue(cw->cpick.scales[which], value);
changeLabel(cw, which);
}
static SetScaleFloatValue(CpickWidget cw, int which, int value)
{
XmScaleSetValue(cw->cpick.scales[which], (int) ((FBASE*value)/MBASE));
changeLabel(cw, which);
}
static XtGeometryResult GeometryManager(w, request, reply)
Widget w;
XtWidgetGeometry *request;
XtWidgetGeometry *reply; /* RETURN */
{
return XtGeometryYes;
}
static void ChangeManaged(cw)
CpickWidget cw;
{
XtMakeResizeRequest((Widget) cw, getD(cw->cpick.tlevel, XmNwidth),
getD(cw->cpick.tlevel, XmNheight),
NULL, NULL);
}
static void Realize( gw, valueMask, attributes )
Widget gw;
XtValueMask *valueMask;
XSetWindowAttributes *attributes;
{
CpickWidget cw = (CpickWidget) gw;
Dimension newHeight;
XtCreateWindow( gw, InputOutput, (Visual *)CopyFromParent,
*valueMask, attributes );
XtRealizeWidget(cw->cpick.tlevel);
count = 0;
XtSetArg(args[count], XmNheight, &newHeight); count++;
XtGetValues(cw->cpick.hexText, args, count);
if (newHeight > cw->cpick.oldHeight) {
count = 0;
XtSetArg(args[count], XmNmarginHeight,
(newHeight-cw->cpick.oldHeight)/2); count++;
XtSetValues(cw->cpick.hexText, args, count);
}
}
static void Resize( gw )
Widget gw;
{
CpickWidget cw = (CpickWidget) gw;
XClearWindow( XtDisplay(gw), XtWindow(gw) );
XtResizeWidget(cw->cpick.tlevel, cw->core.width,
cw->core.height, (Dimension) 1);
XClearWindow(XtDisplay(cw->cpick.nlevel), XtWindow(cw->cpick.nlevel) );
doExpose(cw);
}
static Boolean SetValues( current, request, desired )
Widget current, /* what I am */
request, /* what he wants me to be */
desired; /* what I will become */
{
CpickWidget sw = (CpickWidget) desired;
Boolean redraw = TRUE; /* be stupid for now */
sw->cpick.oldvalue = *(sw->cpick.allocated);
doNew(sw);
return(redraw);
}
static updateBox(cw)
CpickWidget cw;
{
XStoreColor(XtDisplay(cw),
cw->cpick.cmap,
cw->cpick.allocated);
}
void CenterWidget(parent, child)
Widget parent, child;
{
Position x, y;
x = (getD(parent, XmNwidth) - getD(child, XmNwidth)) / 2;
y = (getD(parent, XmNheight) - getD(child, XmNheight)) / 2;
if (x < 0) x = 0;
XtMoveWidget(child, x, y);
}
static char hexDigit(v)
int v;
{
if (v < 10)
return '0'+v;
else
return 'a'+(v-10);
}
static int unhexChar(ch)
char ch;
{
if (ch >= '0' && ch <= '9')
return (ch-'0');
else if (ch >= 'a' && ch <= 'f')
return (ch-'a'+10);
else if (ch >= 'A' && ch <= 'F')
return (ch-'A'+10);
else
return -1;
}
static Boolean hexChars(s)
char *s;
{
int each;
for (each=0; each<strlen(s); each++) {
if (unhexChar(s[each]) == -1)
return(FALSE);
}
return(TRUE);
}
static createHex(r, g, b, s)
int r, g, b;
char s[];
{
sprintf(s, "#%c%c%c%c%c%c",
hexDigit(256*r/MBASE/16),
hexDigit(256*r/MBASE % 16),
hexDigit(256*g/MBASE/16),
hexDigit(256*g/MBASE % 16),
hexDigit(256*b/MBASE/16),
hexDigit(256*b/MBASE % 16));
}
static changeRGB(cw, which)
CpickWidget cw;
int which;
{
RGB rgb;
HSV hsv;
CMY cmy;
char str[13];
if (cw->cpick.matched) {
setMlabelStr(cw, NULLSTR);
}
if (which < H) {
rgb.r = cw->cpick.values[R]*RATIO;
rgb.g = cw->cpick.values[G]*RATIO;
rgb.b = cw->cpick.values[B]*RATIO;
hsv = RGBToHSV(rgb);
cw->cpick.values[H] = (int) (hsv.h*(MBASE-1));
cw->cpick.values[S] = (int) (hsv.s*(MBASE-1));
cw->cpick.values[V] = (int) (hsv.v*(MBASE-1));
SetScaleFloatValue(cw, H, cw->cpick.values[H]);
SetScaleFloatValue(cw, S, cw->cpick.values[S]);
SetScaleFloatValue(cw, V, cw->cpick.values[V]);
cmy = RGBToCMY(rgb);
cw->cpick.values[C] = cmy.c*RATIO/MAXIMUM;
cw->cpick.values[M] = cmy.m*RATIO/MAXIMUM;
cw->cpick.values[Y] = cmy.y*RATIO/MAXIMUM;
SetScaleValue(cw, C, cw->cpick.values[C]);
SetScaleValue(cw, M, cw->cpick.values[M]);
SetScaleValue(cw, Y, cw->cpick.values[Y]);
} else if (which < C) {
hsv.h = cw->cpick.values[H]/(float) (MBASE-1);
hsv.s = cw->cpick.values[S]/(float) (MBASE-1);
hsv.v = cw->cpick.values[V]/(float) (MBASE-1);
rgb = HSVToRGB(hsv);
cw->cpick.values[R] = rgb.r*RATIO/MAXIMUM;
cw->cpick.values[G] = rgb.g*RATIO/MAXIMUM;
cw->cpick.values[B] = rgb.b*RATIO/MAXIMUM;
SetScaleValue(cw, R, cw->cpick.values[R]);
SetScaleValue(cw, G, cw->cpick.values[G]);
SetScaleValue(cw, B, cw->cpick.values[B]);
cmy = RGBToCMY(rgb);
cw->cpick.values[C] = cmy.c*RATIO/MAXIMUM;
cw->cpick.values[M] = cmy.m*RATIO/MAXIMUM;
cw->cpick.values[Y] = cmy.y*RATIO/MAXIMUM;
SetScaleValue(cw, C, cw->cpick.values[C]);
SetScaleValue(cw, M, cw->cpick.values[M]);
SetScaleValue(cw, Y, cw->cpick.values[Y]);
} else {
cmy.c = cw->cpick.values[C]*RATIO;
cmy.m = cw->cpick.values[M]*RATIO;
cmy.y = cw->cpick.values[Y]*RATIO;
rgb = CMYToRGB(cmy);
cw->cpick.values[R] = rgb.r*RATIO/MAXIMUM;
cw->cpick.values[G] = rgb.g*RATIO/MAXIMUM;
cw->cpick.values[B] = rgb.b*RATIO/MAXIMUM;
SetScaleValue(cw, R, cw->cpick.values[R]);
SetScaleValue(cw, G, cw->cpick.values[G]);
SetScaleValue(cw, B, cw->cpick.values[B]);
hsv = RGBToHSV(rgb);
cw->cpick.values[H] = (int) (hsv.h*(MBASE-1));
cw->cpick.values[S] = (int) (hsv.s*(MBASE-1));
cw->cpick.values[V] = (int) (hsv.v*(MBASE-1));
SetScaleFloatValue(cw, H, cw->cpick.values[H]);
SetScaleFloatValue(cw, S, cw->cpick.values[S]);
SetScaleFloatValue(cw, V, cw->cpick.values[V]);
}
createHex(cw->cpick.values[R], cw->cpick.values[G], cw->cpick.values[B],
str);
XmTextFieldSetString(cw->cpick.hexText, str);
cw->cpick.allocated->red = cw->cpick.values[R]*RATIO;
cw->cpick.allocated->green = cw->cpick.values[G]*RATIO;
cw->cpick.allocated->blue = cw->cpick.values[B]*RATIO;
changePalette(cw, FALSE);
if (XtIsRealized((Widget) cw) && cw->cpick.changeProc) {
XtCallCallbacks((Widget) cw, XmNchangeProc,
(XtPointer) (cw->cpick.allocated));
}
}
static update(cmd, client_data, call_data)
Widget cmd;
XtPointer client_data;
XtPointer call_data;
{
int which;
CpickWidget cw = (CpickWidget) client_data;
XmScaleCallbackStruct *cb = (XmScaleCallbackStruct *) call_data;
cw = (CpickWidget) client_data;
for (which=0; which<NUM; which++) {
if (cw->cpick.scales[which] == cmd) {
if (which >= H && which <= V) {
cw->cpick.values[which] = (cb->value*MBASE)/FBASE;
} else {
cw->cpick.values[which] = cb->value;
}
changeLabel(cw, which);
break;
}
}
changeRGB(cw, which);
updateBox(cw);
}
static newRGB(cw, r, g, b)
CpickWidget cw;
unsigned short r, g, b;
{
cw->cpick.values[R] = r/RATIO;
cw->cpick.values[G] = g/RATIO;
cw->cpick.values[B] = b/RATIO;
SetScaleValue(cw, R, cw->cpick.values[R]);
SetScaleValue(cw, G, cw->cpick.values[G]);
SetScaleValue(cw, B, cw->cpick.values[B]);
changeRGB(cw, R);
updateBox(cw);
}
static changeLabel(cw, which)
CpickWidget cw;
int which;
{
char str[10];
XmString xs;
if (which < H || which > V) {
sprintf(str, "%-5d", cw->cpick.values[which]);
} else {
sprintf(str, "%-5.3f", cw->cpick.values[which]/(float) (MBASE-1));
}
count = 0;
xs = XmStringCreateSimple(str);
XtSetArg(args[count], XmNlabelString, xs); count++;
XtSetValues(cw->cpick.labels[which], args, count);
}
static createScales(cw)
CpickWidget cw;
{
int each;
Widget scaleSet, scale;
XColor xc, ignore;
XmString xs, empty, lstring;
char str[5];
Dimension height = 0, maxWidth = 0, width;
empty = XmStringCreateSimple(NULLSTR);
lstring = XmStringCreateSimple("0.000");
count = 0;
XtSetArg(args[count], XmNtopAttachment, XmATTACH_FORM); count++;
XtSetArg(args[count], XmNtopOffset, BORDER_MARGIN); count++;
XtSetArg(args[count], XmNleftAttachment, XmATTACH_FORM); count++;
XtSetArg(args[count], XmNleftOffset, BORDER_MARGIN); count++;
XtSetArg(args[count], XmNbottomAttachment, XmATTACH_FORM); count++;
XtSetArg(args[count], XmNbottomOffset, BORDER_MARGIN); count++;
XtSetArg(args[count], XmNadjustMargin, False); count++;
XtSetArg(args[count], XmNspacing, SCALE_SET_SPACING); count++;
XtSetArg(args[count], XmNorientation, XmVERTICAL); count++;
XtSetArg(args[count], XmNpacking, XmPACK_COLUMN); count++;
cw->cpick.scaleSets = XmCreateRowColumn(cw->cpick.tlevel, "scaleSets",
args, count);
XtManageChild(cw->cpick.scaleSets);
for (each=0; each<NUM; each++) {
if (each % 3 == 0) {
count = 0;
XtSetArg(args[count], XmNadjustMargin, False); count++;
XtSetArg(args[count], XmNmarginWidth, 0); count++;
XtSetArg(args[count], XmNmarginHeight, 0); count++;
XtSetArg(args[count], XmNspacing, SCALE_SPACING); count++;
XtSetArg(args[count], XmNorientation, XmVERTICAL); count++;
XtSetArg(args[count], XmNpacking, XmPACK_COLUMN); count++;
XtSetArg(args[count], XmNentryAlignment, XmALIGNMENT_BEGINNING); count++;
scaleSet = XmCreateRowColumn(cw->cpick.scaleSets, "scaleSet",
args, count);
XtManageChild(scaleSet);
}
count = 0;
XtSetArg(args[count], XmNadjustMargin, False); count++;
XtSetArg(args[count], XmNmarginWidth, 0); count++;
XtSetArg(args[count], XmNmarginHeight, 0); count++;
XtSetArg(args[count], XmNspacing, INTRA_SCALE_SPACING); count++;
XtSetArg(args[count], XmNorientation, XmHORIZONTAL); count++;
XtSetArg(args[count], XmNpacking, XmPACK_TIGHT); count++;
XtSetArg(args[count], XmNentryAlignment, XmALIGNMENT_BEGINNING); count++;
scale = XmCreateRowColumn(scaleSet, "scaleGroup", args, count);
XtManageChild(scale);
count = 0;
sprintf(str, "%c", STRING[each]);
xs = XmStringCreateSimple(str);
XtSetArg(args[count], XmNmarginWidth, 0); count++;
XtSetArg(args[count], XmNmarginHeight, 0); count++;
XtSetArg(args[count], XmNrecomputeSize, False); count++;
XtSetArg(args[count], XmNlabelString, xs); count++;
if (cw->cpick.usecolors && ((each < H) || (each > V))) {
XAllocNamedColor(XtDisplay(cw),
cw->cpick.cmap,
colors[each], &xc, &ignore);
XtSetArg(args[count], XmNforeground, xc.pixel); count++;
cw->cpick.names[each] = XmCreateLabel(scale, "name", args, count);
} else {
cw->cpick.names[each] = XmCreateLabelGadget(scale, "name", args, count);
}
XtManageChild(cw->cpick.names[each]);
XmStringFree(xs);
if (!height) {
count = 0;
XtSetArg(args[count], XmNheight, &height); count++;
XtGetValues(cw->cpick.names[each], args, count);
}
count = 0;
XtSetArg(args[count], XmNwidth, &width); count++;
XtGetValues(cw->cpick.names[each], args, count);
if (width > maxWidth) {
maxWidth = width;
}
count = 0;
XtSetArg(args[count], XmNwidth, SCALE_WIDTH); count++;
XtSetArg(args[count], XmNshowValue, False); count++;
XtSetArg(args[count], XmNorientation, XmHORIZONTAL); count++;
XtSetArg(args[count], XmNtitleString, empty); count++;
XtSetArg(args[count], XmNheight, height); count++;
XtSetArg(args[count], XmNminimum, 0); count++;
if (each < H || each > V) {
XtSetArg(args[count], XmNmaximum, MBASE-1); count++;
} else {
XtSetArg(args[count], XmNmaximum, FBASE-1); count++;
XtSetArg(args[count], XmNdecimalPoints, 3); count++;
}
cw->cpick.scales[each] = XmCreateScale(scale, "scale", args, count);
XtManageChild(cw->cpick.scales[each]);
XtAddCallback(cw->cpick.scales[each], XmNvalueChangedCallback,
(XtCallbackProc) update, (XtPointer) cw);
XtAddCallback(cw->cpick.scales[each], XmNdragCallback,
(XtCallbackProc) update, (XtPointer) cw);
count = 0;
XtSetArg(args[count], XmNlabelString, lstring); count++;
XtSetArg(args[count], XmNrecomputeSize, False); count++;
cw->cpick.labels[each] = XmCreateLabelGadget(scale, "label", args, count);
XtManageChild(cw->cpick.labels[each]);
}
count = 0;
XtSetArg(args[count], XmNwidth, maxWidth); count++;
for (each=0; each<NUM; each++) {
XtSetValues(cw->cpick.names[each], args, count);
}
XmStringFree(empty);
XmStringFree(lstring);
}
static void dohex(cmd, client_data, call_data)
Widget cmd;
XtPointer client_data;
XtPointer call_data;
{
CpickWidget cw = (CpickWidget) client_data;
char *response, *str;
response = str = XmTextGetString(cw->cpick.hexText);
if (response[0] == '#') {
response++;
}
if ((strlen(response) != 6 && strlen(response) != 3)
|| !hexChars(response)) {
setMlabelStr(cw, "Illegal hex string.");
XBell(XtDisplay(cw), 0);
cw->cpick.matched = True;
} else if (strlen(response) == 6) {
cw->cpick.allocated->red =
(unhexChar(response[0])*16+unhexChar(response[1]))*RATIO;
cw->cpick.allocated->green =
(unhexChar(response[2])*16+unhexChar(response[3]))*RATIO;
cw->cpick.allocated->blue =
(unhexChar(response[4])*16+unhexChar(response[5]))*RATIO;
cw->cpick.keep = FALSE;
doNew(cw);
} else if (strlen(response) == 3) {
cw->cpick.allocated->red = unhexChar(response[0])*16*RATIO;
cw->cpick.allocated->green = unhexChar(response[1])*16*RATIO;
cw->cpick.allocated->blue = unhexChar(response[2])*16*RATIO;
cw->cpick.keep = FALSE;
doNew(cw);
}
XtFree(str);
}
static dopalette(cmd, client_data, call_data)
Widget cmd;
XtPointer client_data;
XtPointer call_data;
{
CpickWidget cw = (CpickWidget) client_data;
XmString xs;
cw->cpick.wide = (cw->cpick.wide+1) % (RANGE+1);
if (cw->cpick.wide == WIDE) {
xs = XmStringCreateSimple(WIDE_STRING);
} else if (cw->cpick.wide == RANGE) {
xs = XmStringCreateSimple(RANGE_STRING);
} else {
xs = XmStringCreateSimple(NARROW_STRING);
}
count = 0;
XtSetArg(args[count], XmNlabelString, xs); count++;
XtSetValues(cw->cpick.paletteButton, args, count);
XmStringFree(xs);
changePalette(cw, TRUE);
}
static domatch(cmd, client_data, call_data)
Widget cmd;
XtPointer client_data;
XtPointer call_data;
{
CpickWidget cw = (CpickWidget) client_data;
cw->cpick.matched = TRUE;
matchPalette(cw);
}
static createBox(cw)
CpickWidget cw;
{
Widget match;
XmString xs;
count = 0;
XtSetArg(args[count], XmNadjustMargin, False); count++;
XtSetArg(args[count], XmNmarginWidth, 0); count++;
XtSetArg(args[count], XmNmarginHeight, 0); count++;
XtSetArg(args[count], XmNtopAttachment, XmATTACH_FORM); count++;
XtSetArg(args[count], XmNtopOffset, BORDER_MARGIN); count++;
XtSetArg(args[count], XmNrightAttachment, XmATTACH_FORM); count++;
XtSetArg(args[count], XmNrightOffset, BORDER_MARGIN); count++;
XtSetArg(args[count], XmNorientation, XmVERTICAL); count++;
XtSetArg(args[count], XmNpacking, XmPACK_COLUMN); count++;
XtSetArg(args[count], XmNentryAlignment, XmALIGNMENT_CENTER); count++;
XtSetArg(args[count], XmNspacing, BUTTON_SPACING); count++;
cw->cpick.boxButtons = XmCreateRowColumn(cw->cpick.tlevel, "boxButtons",
args, count);
XtManageChild(cw->cpick.boxButtons);
count = 0;
XtSetArg(args[count], XmNcolumns, 8); count++;
XtSetArg(args[count], XmNmarginHeight, 0); count++;
cw->cpick.hexText = XmCreateTextField(cw->cpick.boxButtons, "hexText",
args, count);
XtManageChild(cw->cpick.hexText);
XtAddCallback(cw->cpick.hexText, XmNactivateCallback,
(XtCallbackProc) dohex, (XtPointer) cw);
count = 0;
XtSetArg(args[count], XmNheight, &cw->cpick.oldHeight); count++;
XtGetValues(cw->cpick.hexText, args, count);
count = 0;
xs = XmStringCreateSimple(RANGE_STRING);
XtSetArg(args[count], XmNlabelString, xs); count++;
XtSetArg(args[count], XmNrecomputeSize, False); count++;
XtSetArg(args[count], XmNmarginLeft, 0); count++;
XtSetArg(args[count], XmNmarginRight, 0); count++;
XtSetArg(args[count], XmNmarginTop, 0); count++;
XtSetArg(args[count], XmNmarginBottom, 0); count++;
cw->cpick.paletteButton = XmCreatePushButton(cw->cpick.boxButtons,
"paletteButton", args, count);
XtManageChild(cw->cpick.paletteButton);
XmStringFree(xs);
XtAddCallback(cw->cpick.paletteButton, XmNactivateCallback,
(XtCallbackProc) dopalette, (XtPointer) cw);
count = 0;
xs = XmStringCreateSimple(MATCH_STRING);
XtSetArg(args[count], XmNlabelString, xs); count++;
XtSetArg(args[count], XmNrecomputeSize, False); count++;
XtSetArg(args[count], XmNmarginLeft, 0); count++;
XtSetArg(args[count], XmNmarginRight, 0); count++;
XtSetArg(args[count], XmNmarginTop, 0); count++;
XtSetArg(args[count], XmNmarginBottom, 0); count++;
cw->cpick.matchButton = XmCreatePushButton(cw->cpick.boxButtons,
"matchButton", args, count);
XtManageChild(cw->cpick.matchButton);
XmStringFree(xs);
XtAddCallback(cw->cpick.matchButton, XmNactivateCallback,
(XtCallbackProc) domatch, (XtPointer) cw);
count = 0;
XtSetArg(args[count], XmNtopAttachment, XmATTACH_FORM); count++;
XtSetArg(args[count], XmNtopOffset, BORDER_MARGIN); count++;
XtSetArg(args[count], XmNleftAttachment, XmATTACH_WIDGET); count++;
XtSetArg(args[count], XmNleftWidget, cw->cpick.scaleSets); count++;
XtSetArg(args[count], XmNleftOffset, INTER_SPACING); count++;
XtSetArg(args[count], XmNrightAttachment, XmATTACH_WIDGET); count++;
XtSetArg(args[count], XmNrightWidget, cw->cpick.boxButtons); count++;
XtSetArg(args[count], XmNrightOffset, INTER_SPACING); count++;
XtSetArg(args[count], XmNshadowType, XmSHADOW_IN); count++;
XtSetArg(args[count], XmNmarginWidth, BOX_MARGIN); count++;
XtSetArg(args[count], XmNmarginHeight, BOX_MARGIN); count++;
cw->cpick.bcontainer = XmCreateFrame(cw->cpick.tlevel, "bcontainer",
args, count);
XtManageChild(cw->cpick.bcontainer);
count = 0;
XtSetArg(args[count], XmNshadowType, XmSHADOW_OUT); count++;
XtSetArg(args[count], XmNshadowThickness, BOX_SHADOW_THICKNESS); count++;
cw->cpick.bframe = XmCreateFrame(cw->cpick.bcontainer, "bframe",
args, count);
XtManageChild(cw->cpick.bframe);
count = 0;
cw->cpick.box = XmCreateDrawingArea(cw->cpick.bframe, "box", args, count);
XtManageChild(cw->cpick.box);
}
static doNew(cw)
CpickWidget cw;
{
newRGB(cw,
cw->cpick.allocated->red,
cw->cpick.allocated->green,
cw->cpick.allocated->blue);
if (cw->cpick.box) {
count = 0;
XtSetArg(args[count], XmNbackground, cw->cpick.allocated->pixel); count++;
XtSetValues(cw->cpick.box, args, count);
}
}
static nButtonHandler(w, val, event)
Widget w;
struct vals *val;
XButtonEvent *event;
{
int newpix, v;
XColor xc;
CpickWidget cw = val->cw;
if (!val->ih || !val->iw) {
return;
}
v = (event->x-val->x0)/val->iw + ((event->y-val->y0)/val->ih)*val->rownum;
newpix = val->pix(cw, v);
if (newpix != MAXIMUM) {
xc.pixel = newpix;
XQueryColor(XtDisplay(cw), cw->cpick.cmap, &xc);
cw->cpick.allocated->red = xc.red;
cw->cpick.allocated->green = xc.green;
cw->cpick.allocated->blue = xc.blue;
cw->cpick.keep = TRUE;
doNew(cw);
if (cw->cpick.matched) {
setMlabelStr(cw, cw->cpick.mnames[v]);
}
}
}
static unsigned long nPixel(cw, each)
CpickWidget cw;
int each;
{
if (each < cw->cpick.nearpixels)
return cw->cpick.nearcells[each].pixel;
else
return MAXIMUM;
}
static createGrid(wid, num, x0, y0, h, w, proc, val, pix)
Widget wid;
int num;
Position x0, y0;
Dimension h, w;
XtEventHandler proc;
struct vals *val;
PixProc pix;
{
int each, x, y, hs, ws;
double hsize, wsize;
GC gc;
XGCValues gcv;
unsigned long black;
val->pix = pix;
hsize = sqrt((double) num*VNEARRATIO/HNEARRATIO);
wsize = ceil(hsize*HNEARRATIO/VNEARRATIO);
hsize = ceil(hsize);
val->ih = (int) ((h-1)/hsize);
val->iw = (int) ((w-1)/wsize);
val->rownum = (int) wsize;
hs = (int) hsize*val->ih+1;
ws = (int) wsize*val->iw+1;
/*
XtMoveWidget(wid, (Position) x0, (Position) y0);
XtResizeWidget(wid, w, h, (Dimension) 1);
*/
val->y0 = (h-hs)/2;
val->x0 = (w-ws)/2;
gcv.function = GXcopy;
gcv.fill_style = FillSolid;
black = XBlackPixel(XtDisplay(wid),
XDefaultScreen(XtDisplay(wid)));
gcv.background = black;
gc = XCreateGC(XtDisplay(wid), XtWindow(wid),
GCBackground | GCFunction | GCFillStyle, &gcv);
XSync(XtDisplay(wid),0);
for (each=0; each<num; each++) {
x = (each % val->rownum)*val->iw;
y = (each/val->rownum)*val->ih;
XSetForeground(XtDisplay(wid), gc, pix(val->cw, each));
XFillRectangle(XtDisplay(wid), XtWindow(wid), gc, val->x0+x, val->y0+y,
val->iw, val->ih);
XSetForeground(XtDisplay(wid), gc, black);
XDrawRectangle(XtDisplay(wid), XtWindow(wid), gc, val->x0+x, val->y0+y,
val->iw, val->ih);
}
XtAddEventHandler(wid, ButtonPressMask, FALSE, (XtEventHandler) proc,
(XtPointer) val);
XFreeGC(XtDisplay(wid), gc);
}
static doExpose(cw)
CpickWidget cw;
{
nval.cw = cw;
createGrid(cw->cpick.nlevel, (int) cw->cpick.nearpixels,
getP(cw->cpick.nlevel, XmNx),
getP(cw->cpick.nlevel, XmNy),
getD(cw->cpick.nlevel, XmNheight),
getD(cw->cpick.nlevel, XmNwidth),
nButtonHandler, &nval, nPixel);
}
static nlevel_expose(w, client_data, call_data)
Widget w;
XtPointer client_data;
XtPointer call_data;
{
XEvent ev;
CpickWidget cw = (CpickWidget) client_data;
XFlush(XtDisplay(w));
while (XCheckWindowEvent(XtDisplay(w), XtWindow(w), ExposureMask, &ev)) {
/* eat it */
}
doExpose(cw);
}
static doselect(cmd, client_data, call_data)
Widget cmd;
XtPointer client_data;
XtPointer call_data;
{
CpickWidget cw = (CpickWidget) client_data;
undomatch(cw);
if (cw->cpick.selectProc) {
XtCallCallbacks((Widget) cw, XmNselectProc,
(XtPointer)(cw->cpick.allocated));
}
}
static docancel(cmd, client_data, call_data)
Widget cmd;
XtPointer client_data;
XtPointer call_data;
{
CpickWidget cw = (CpickWidget) client_data;
*(cw->cpick.allocated) = cw->cpick.oldvalue;
doNew(cw);
}
static dorestore(cmd, client_data, call_data)
Widget cmd;
XtPointer client_data;
XtPointer call_data;
{
CpickWidget cw = (CpickWidget) client_data;
if (cw->cpick.restoreProc) {
XtCallCallbacks((Widget) cw, XmNrestoreProc,
(XtPointer)(cw->cpick.allocated));
}
changePalette(cw, TRUE);
}
static dook(cmd, client_data, call_data)
Widget cmd;
XtPointer client_data;
XtPointer call_data;
{
CpickWidget cw = (CpickWidget) client_data;
if (cw->cpick.okProc) {
XtCallCallbacks((Widget) cw, XmNokProc,
(XtPointer)(cw->cpick.allocated));
}
}
static dohelp(cmd, client_data, call_data)
Widget cmd;
XtPointer client_data;
XtPointer call_data;
{
CpickWidget cw = (CpickWidget) client_data;
if (cw->cpick.helpProc) {
XtCallCallbacks((Widget) cw, XmNhelpProc,
(XtPointer)(cw->cpick.allocated));
}
}
static createCommands(cw)
CpickWidget cw;
{
Widget buffer;
XmString xs;
count = 0;
XtSetArg(args[count], XmNadjustMargin, False); count++;
XtSetArg(args[count], XmNmarginWidth, 0); count++;
XtSetArg(args[count], XmNmarginHeight, 0); count++;
XtSetArg(args[count], XmNrightAttachment, XmATTACH_FORM); count++;
XtSetArg(args[count], XmNrightOffset, BORDER_MARGIN); count++;
XtSetArg(args[count], XmNbottomAttachment, XmATTACH_FORM); count++;
XtSetArg(args[count], XmNbottomOffset, BORDER_MARGIN); count++;
XtSetArg(args[count], XmNorientation, XmHORIZONTAL); count++;
XtSetArg(args[count], XmNpacking, XmPACK_COLUMN); count++;
XtSetArg(args[count], XmNentryAlignment, XmALIGNMENT_CENTER); count++;
XtSetArg(args[count], XmNspacing, BUTTON_SPACING); count++;
cw->cpick.commandBox = XmCreateRowColumn(cw->cpick.tlevel, "commandBox",
args, count);
XtManageChild(cw->cpick.commandBox);
count = 0;
XtSetArg(args[count], XmNleftAttachment, XmATTACH_WIDGET); count++;
XtSetArg(args[count], XmNleftWidget, cw->cpick.scaleSets); count++;
XtSetArg(args[count], XmNleftOffset, INTER_SPACING); count++;
XtSetArg(args[count], XmNrightAttachment, XmATTACH_WIDGET); count++;
XtSetArg(args[count], XmNrightWidget, cw->cpick.commandBox); count++;
XtSetArg(args[count], XmNwidth, 1); count++;
buffer = XmCreateDrawingArea(cw->cpick.tlevel, "commandBuffer", args, count);
XtManageChild(buffer);
if (cw->cpick.selectlabel) {
count = 0;
xs = XmStringCreateSimple(cw->cpick.selectlabel);
XtSetArg(args[count], XmNlabelString, xs); count++;
XtSetArg(args[count], XmNmarginLeft, 0); count++;
XtSetArg(args[count], XmNmarginRight, 0); count++;
XtSetArg(args[count], XmNmarginTop, 0); count++;
XtSetArg(args[count], XmNmarginBottom, 0); count++;
cw->cpick.select0 = XmCreatePushButton(cw->cpick.commandBox, "select",
args, count);
XtManageChild(cw->cpick.select0);
XtAddCallback(cw->cpick.select0, XmNactivateCallback,
(XtCallbackProc) doselect, (XtPointer) cw);
XmStringFree(xs);
}
if (cw->cpick.cancellabel) {
count = 0;
xs = XmStringCreateSimple(cw->cpick.cancellabel);
XtSetArg(args[count], XmNlabelString, xs); count++;
XtSetArg(args[count], XmNmarginLeft, 0); count++;
XtSetArg(args[count], XmNmarginRight, 0); count++;
XtSetArg(args[count], XmNmarginTop, 0); count++;
XtSetArg(args[count], XmNmarginBottom, 0); count++;
cw->cpick.cancel = XmCreatePushButton(cw->cpick.commandBox, "cancel",
args, count);
XtManageChild(cw->cpick.cancel);
XtAddCallback(cw->cpick.cancel, XmNactivateCallback,
(XtCallbackProc) docancel, (XtPointer) cw);
XmStringFree(xs);
}
if (cw->cpick.restorelabel) {
count = 0;
xs = XmStringCreateSimple(cw->cpick.restorelabel);
XtSetArg(args[count], XmNlabelString, xs); count++;
XtSetArg(args[count], XmNmarginLeft, 0); count++;
XtSetArg(args[count], XmNmarginRight, 0); count++;
XtSetArg(args[count], XmNmarginTop, 0); count++;
XtSetArg(args[count], XmNmarginBottom, 0); count++;
cw->cpick.restore = XmCreatePushButton(cw->cpick.commandBox, "restore",
args, count);
XtManageChild(cw->cpick.restore);
XtAddCallback(cw->cpick.restore, XmNactivateCallback,
(XtCallbackProc) dorestore, (XtPointer) cw);
XmStringFree(xs);
}
if (cw->cpick.oklabel) {
count = 0;
xs = XmStringCreateSimple(cw->cpick.oklabel);
XtSetArg(args[count], XmNlabelString, xs); count++;
XtSetArg(args[count], XmNmarginLeft, 0); count++;
XtSetArg(args[count], XmNmarginRight, 0); count++;
XtSetArg(args[count], XmNmarginTop, 0); count++;
XtSetArg(args[count], XmNmarginBottom, 0); count++;
cw->cpick.ok = XmCreatePushButton(cw->cpick.commandBox, "ok",
args, count);
XtManageChild(cw->cpick.ok);
XtAddCallback(cw->cpick.ok, XmNactivateCallback,
(XtCallbackProc) dook, (XtPointer) cw);
XmStringFree(xs);
}
if (cw->cpick.helplabel) {
count = 0;
xs = XmStringCreateSimple(cw->cpick.helplabel);
XtSetArg(args[count], XmNlabelString, xs); count++;
XtSetArg(args[count], XmNmarginLeft, 0); count++;
XtSetArg(args[count], XmNmarginRight, 0); count++;
XtSetArg(args[count], XmNmarginTop, 0); count++;
XtSetArg(args[count], XmNmarginBottom, 0); count++;
cw->cpick.help = XmCreatePushButton(cw->cpick.commandBox, "help",
args, count);
XtManageChild(cw->cpick.help);
XtAddCallback(cw->cpick.help, XmNactivateCallback,
(XtCallbackProc) dohelp, (XtPointer) cw);
XmStringFree(xs);
}
count = 0;
XtSetArg(args[count], XmNleftAttachment, XmATTACH_WIDGET); count++;
XtSetArg(args[count], XmNleftWidget, cw->cpick.scaleSets); count++;
XtSetArg(args[count], XmNleftOffset, INTER_SPACING); count++;
XtSetArg(args[count], XmNrightAttachment, XmATTACH_FORM); count++;
XtSetArg(args[count], XmNrightOffset, BORDER_MARGIN); count++;
XtSetArg(args[count], XmNbottomAttachment, XmATTACH_WIDGET); count++;
XtSetArg(args[count], XmNbottomWidget, cw->cpick.commandBox); count++;
XtSetArg(args[count], XmNbottomOffset, INTER_SPACING); count++;
cw->cpick.mframe = XmCreateFrame(cw->cpick.tlevel, "mframe", args, count);
XtManageChild(cw->cpick.mframe);
count = 0;
xs = XmStringCreateSimple(NULLSTR);
XtSetArg(args[count], XmNlabelString, xs); count++;
XtSetArg(args[count], XmNalignment, XmALIGNMENT_CENTER); count++;
XtSetArg(args[count], XmNrecomputeSize, False); count++;
cw->cpick.mlabel = XmCreateLabel(cw->cpick.mframe, "mlabel", args, count);
XtManageChild(cw->cpick.mlabel);
XmStringFree(xs);
cw->cpick.matched = FALSE;
}
static initPalette(cw)
CpickWidget cw;
{
unsigned long cells[MAXPIXELS];
int each;
if (!XAllocColorCells(XtDisplay(cw), cw->cpick.cmap, FALSE, NULL, 0,
cells, (int) cw->cpick.nearpixels)) {
fprintf(stderr, "Cpick: Can't allocate %d cells for palette.\n", (int) cw->cpick.nearpixels);
exit(1);
}
for (each=0; each<(int) cw->cpick.nearpixels; each++) {
cw->cpick.nearcells[each].pixel = cells[each];
cw->cpick.nearcells[each].flags = DoRed | DoGreen | DoBlue;
}
changePalette(cw, TRUE);
}
static changePalette(cw, new)
CpickWidget cw;
Boolean new;
{
int each, each2, r, g, b, nr, ng, nb, eachr, eachg, eachb;
int delta, halfr, halfg, halfb, near;
double hueinc;
RGB rgb;
HSV hsv;
int mods[MAXPIXELS][3], nummods;
if (new) {
undomatch(cw);
}
if (cw->cpick.keep) {
cw->cpick.keep = FALSE;
} else {
if (cw->cpick.wide == NARROW) {
halfr = halfg = halfb = (int) cw->cpick.nearpixels/2;
r = cw->cpick.allocated->red;
g = cw->cpick.allocated->green;
b = cw->cpick.allocated->blue;
for (each=0; each<(int) cw->cpick.nearpixels/2; each++) {
if (r-halfr*NARROWNEAR < 0)
halfr--;
if (r+((int) cw->cpick.nearpixels-1-halfr)*NARROWNEAR >= MAXIMUM)
halfr++;
if (g-halfg*NARROWNEAR < 0)
halfg--;
if (g+((int) cw->cpick.nearpixels-1-halfg)*NARROWNEAR >= MAXIMUM)
halfg++;
if (b-halfb*NARROWNEAR < 0)
halfb--;
if (b+((int) cw->cpick.nearpixels-1-halfb)*NARROWNEAR >= MAXIMUM)
halfb++;
}
halfb = halfg = halfr = (halfr+halfg+halfb)/3;
for (each=0; each<(int) cw->cpick.nearpixels; each++) {
nr = r+(each-halfr)*NARROWNEAR;
ng = g+(each-halfg)*NARROWNEAR;
nb = b+(each-halfb)*NARROWNEAR;
if (nr < 0)
nr = 0;
if (ng < 0)
ng = 0;
if (nb < 0)
nb = 0;
if (nr >= MAXIMUM)
nr = MAXIMUM-1;
if (ng >= MAXIMUM)
ng = MAXIMUM-1;
if (nb >= MAXIMUM)
nb = MAXIMUM-1;
cw->cpick.nearcells[each].red = nr;
cw->cpick.nearcells[each].green = ng;
cw->cpick.nearcells[each].blue = nb;
}
XStoreColors(XtDisplay(cw), cw->cpick.cmap, cw->cpick.nearcells,
(int) cw->cpick.nearpixels);
} else if (cw->cpick.wide == WIDE) {
near = WIDENEAR;
delta = (int) exp(log((double) cw->cpick.nearpixels)/3.0);
halfr = halfg = halfb = delta/2;
r = cw->cpick.allocated->red;
g = cw->cpick.allocated->green;
b = cw->cpick.allocated->blue;
for (each=0; each<delta/2; each++) {
if (r-halfr*near < 0)
halfr--;
if (r+(delta-1-halfr)*near >= MAXIMUM)
halfr++;
if (g-halfg*near < 0)
halfg--;
if (g+(delta-1-halfg)*near >= MAXIMUM)
halfg++;
if (b-halfb*near < 0)
halfb--;
if (b+(delta-1-halfb)*near >= MAXIMUM)
halfb++;
}
nummods = 0;
for (eachb=0; eachb<delta; eachb++) {
for (eachg=0; eachg<delta; eachg++) {
for (eachr=0; eachr<(int) cw->cpick.nearpixels/(delta*delta); eachr++) {
mods[nummods][R] = eachr-halfr;
mods[nummods][G] = eachg-halfg;
mods[nummods][B] = eachb-halfb;
nummods++;
}
}
}
for (each=0; each<nummods-1; each++) {
for (each2=each+1; each2<nummods; each2++) {
if (mods[each][R]+mods[each][G]+mods[each][B] >
mods[each2][R]+mods[each2][G]+mods[each2][B]) {
eachr = mods[each][R];
eachg = mods[each][G];
eachb = mods[each][B];
mods[each][R] = mods[each2][R];
mods[each][G] = mods[each2][G];
mods[each][B] = mods[each2][B];
mods[each2][R] = eachr;
mods[each2][G] = eachg;
mods[each2][B] = eachb;
}
}
}
for (each=0; each<nummods; each++) {
cw->cpick.nearcells[each].red = r+mods[each][R]*near;
cw->cpick.nearcells[each].green = g+mods[each][G]*near;
cw->cpick.nearcells[each].blue = b+mods[each][B]*near;
}
XStoreColors(XtDisplay(cw), cw->cpick.cmap, cw->cpick.nearcells,
(int) cw->cpick.nearpixels);
} else if (new) {
hueinc = 1.0/cw->cpick.nearpixels;
hsv.s = hsv.v = 1.0;
hsv.h = 0.0;
for (each=0; each<(int) cw->cpick.nearpixels; each++) {
rgb = HSVToRGB(hsv);
cw->cpick.nearcells[each].red = rgb.r;
cw->cpick.nearcells[each].green = rgb.g;
cw->cpick.nearcells[each].blue = rgb.b;
hsv.h = hsv.h + hueinc;
}
XStoreColors(XtDisplay(cw), cw->cpick.cmap, cw->cpick.nearcells,
(int) cw->cpick.nearpixels);
}
}
}
static undomatch(cw)
CpickWidget cw;
{
XmString xs;
if (cw->cpick.matched) {
cw->cpick.matched = FALSE;
setMlabelStr(cw, NULLSTR);
}
}
static matchPalette(cw)
CpickWidget cw;
{
int each, each2, ct, r, g, b, nr, ng, nb, cr, cg, cb, d;
FILE *fd;
char name[MAXNAME], *sname;
for (each=0; each<MAXPIXELS; each++) {
strcpy(cw->cpick.mnames[each], NULLSTR);
cw->cpick.mdist[each] = MBASE*MBASE*3;
}
cr = cw->cpick.allocated->red/RATIO;
cg = cw->cpick.allocated->green/RATIO;
cb = cw->cpick.allocated->blue/RATIO;
fd = fopen(RGBFILE, "r");
if (fd == NULL || feof(fd)) {
undomatch(cw);
} else {
ct = 0;
r = g = b = -1;
while (!feof(fd)) {
fscanf(fd, "%d %d %d", &nr, &ng, &nb);
fgets(name, MAXNAME, fd);
name[strlen(name)-1] = '\0';
sname = name;
while (sname[0] == ' ' || sname[0] == '\t') {
sname++;
}
if (nr != r || ng != g || nb != b) {
r = nr;
g = ng;
b = nb;
d = (nr-cr)*(nr-cr)+(ng-cg)*(ng-cg)+(nb-cb)*(nb-cb);
for (each = 0; each<ct; each++) {
if (d < cw->cpick.mdist[each]) {
for (each2 = cw->cpick.nearpixels-1; each2>= each; each2--) {
cw->cpick.nearcells[each2+1].red =
cw->cpick.nearcells[each2].red;
cw->cpick.nearcells[each2+1].green =
cw->cpick.nearcells[each2].green;
cw->cpick.nearcells[each2+1].blue =
cw->cpick.nearcells[each2].blue;
cw->cpick.mdist[each2+1] = cw->cpick.mdist[each2];
strcpy(cw->cpick.mnames[each2+1], cw->cpick.mnames[each2]);
}
cw->cpick.nearcells[each].red = nr*RATIO;
cw->cpick.nearcells[each].green = ng*RATIO;
cw->cpick.nearcells[each].blue = nb*RATIO;
cw->cpick.mdist[each] = d;
strcpy(cw->cpick.mnames[each], sname);
if (ct < cw->cpick.nearpixels) {
ct++;
}
#ifdef BUBBLE_MATCH
XStoreColors(XtDisplay(cw), cw->cpick.cmap,
&(cw->cpick.nearcells[each]),
(int) (cw->cpick.nearpixels-each));
#endif
break;
}
}
if (ct < cw->cpick.nearpixels) {
for (each2 = cw->cpick.nearpixels-1; each2>= ct; each2--) {
cw->cpick.nearcells[each2+1].red =
cw->cpick.nearcells[each2].red;
cw->cpick.nearcells[each2+1].green =
cw->cpick.nearcells[each2].green;
cw->cpick.nearcells[each2+1].blue =
cw->cpick.nearcells[each2].blue;
cw->cpick.mdist[each2+1] = cw->cpick.mdist[each2];
strcpy(cw->cpick.mnames[each2+1], cw->cpick.mnames[each2]);
}
cw->cpick.nearcells[ct].red = nr*RATIO;
cw->cpick.nearcells[ct].green = ng*RATIO;
cw->cpick.nearcells[ct].blue = nb*RATIO;
cw->cpick.mdist[ct] = d;
strcpy(cw->cpick.mnames[ct], sname);
#ifdef BUBBLE_MATCH
XStoreColors(XtDisplay(cw), cw->cpick.cmap,
&(cw->cpick.nearcells[ct]),
(int) (cw->cpick.nearpixels-ct));
#endif
ct++;
}
}
}
if (ct != 0 &&
cw->cpick.nearcells[0].red == cw->cpick.allocated->red &&
cw->cpick.nearcells[0].green == cw->cpick.allocated->green &&
cw->cpick.nearcells[0].blue == cw->cpick.allocated->blue) {
setMlabelStr(cw, cw->cpick.mnames[0]);
} else {
setMlabelStr(cw, NULLSTR);
}
fclose(fd);
#ifndef BUBBLE_MATCH
XStoreColors(XtDisplay(cw), cw->cpick.cmap,
cw->cpick.nearcells,
(int) cw->cpick.nearpixels);
#endif
}
}
static void setMlabelStr(cw, str)
CpickWidget cw;
char *str;
{
XmString xs;
xs = XmStringCreateSimple(str);
count = 0;
XtSetArg(args[count], XmNlabelString, xs); count++;
XtSetValues(cw->cpick.mlabel, args, count);
XmStringFree(xs);
}
static createPalette(cw)
CpickWidget cw;
{
count = 0;
XtSetArg(args[count], XmNtopAttachment, XmATTACH_WIDGET); count++;
XtSetArg(args[count], XmNtopWidget, cw->cpick.boxButtons); count++;
XtSetArg(args[count], XmNtopOffset, INTER_SPACING); count++;
XtSetArg(args[count], XmNleftAttachment, XmATTACH_WIDGET); count++;
XtSetArg(args[count], XmNleftWidget, cw->cpick.scaleSets); count++;
XtSetArg(args[count], XmNleftOffset, INTER_SPACING); count++;
XtSetArg(args[count], XmNrightAttachment, XmATTACH_FORM); count++;
XtSetArg(args[count], XmNrightOffset, BORDER_MARGIN); count++;
XtSetArg(args[count], XmNbottomAttachment, XmATTACH_WIDGET); count++;
XtSetArg(args[count], XmNbottomWidget, cw->cpick.mframe); count++;
XtSetArg(args[count], XmNbottomOffset, INTER_SPACING); count++;
cw->cpick.nlevel = XmCreateDrawingArea(cw->cpick.tlevel, "nlevel",
args, count);
XtManageChild(cw->cpick.nlevel);
XtAddCallback(cw->cpick.nlevel, XmNexposeCallback,
(XtCallbackProc) nlevel_expose, (XtPointer) cw);
cw->cpick.wide = RANGE;
cw->cpick.keep = FALSE;
cw->cpick.matched = FALSE;
count = 0;
XtSetArg(args[count], XmNbottomAttachment, XmATTACH_WIDGET); count++;
XtSetArg(args[count], XmNbottomWidget, cw->cpick.nlevel); count++;
XtSetArg(args[count], XmNbottomOffset, INTER_SPACING); count++;
XtSetValues(cw->cpick.bcontainer, args, count);
}
static void Initialize( request, new )
Widget request; /* what the client asked for */
Widget new; /* what we're going to give him */
{
int each, depth;
CpickWidget cw = (CpickWidget) new;
if (!cw->cpick.cmap) {
fprintf(stderr, "Cpick: Must set XmNcmap resource.\n");
exit(1);
} else if (cw->cpick.allocated == NULL) {
fprintf(stderr, "Cpick: Must set XmNallocated resource.\n");
exit(1);
}
count = 0;
cw->cpick.tlevel = XmCreateForm(new, "form", args, count);
XtManageChild(cw->cpick.tlevel);
depth = XDisplayPlanes(XtDisplay(cw),
XDefaultScreen(XtDisplay(cw)));
cw->cpick.inc = INCREMENT;
if (!cw->cpick.inc)
cw->cpick.inc = 1;
createScales(cw);
createBox(cw);
createCommands(cw);
createPalette(cw);
initPalette(cw);
doNew(cw);
if (cw->core.width == 0) {
cw->core.width = 10;
}
if (cw->core.height == 0) {
cw->core.height = 10;
}
}
/**********************************************************************/
Widget
CpickGetBoxFrame(Widget w)
{
CpickWidget cw = (CpickWidget) w;
return cw->cpick.bframe;
}